#include "common_impl.h"


int main(int argc, char **argv)
{   
	char** newargv = malloc((argc+1)*sizeof(char*));
	int j=0;
	int fd;
	struct sockaddr_in dest;

	/* processus intermediaire pour "nettoyer" */
	/* la liste des arguments qu'on va passer */
	/* a la commande a executer vraiment */

	for (j=0; j< argc-2; j++){
		newargv[j] = malloc(sizeof(char)*20);
		strcpy(newargv[j], argv[j+2]);
		//fprintf(stdout,"newargv[%d] : %s -- ", j, newargv[j]);
	}
	newargv[j] = NULL;

	/* creation d'une socket pour se connecter au */
	/* au lanceur et envoyer/recevoir les infos */
	/* necessaires pour la phase dsm_init */
	/*---Initialize server address/port struct---*/
	memset(&dest, 0, sizeof(dest));
	dest.sin_family      = AF_INET;
	inet_pton(dest.sin_family, newargv[0], &(dest.sin_addr));
	dest.sin_port        = htons(atoi(newargv[1]));


	fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0)
	{
		perror("ERROR opening socket");
		exit(1);
	}

	/*---Connect to server---*/
	if (connect(fd, (struct sockaddr *) &dest, sizeof(dest)) < 0)
	{
		perror("ERROR on connecting");
		exit(1);
	}

	printf("Enter message 1\n");
	char buffer[] = "I'm connected!\n";
	if( Sendline(fd, buffer, strlen(buffer)) < 0) { // Envoyer celle-ci au serveur
		puts("Send failed");
		return 1;
	}

	char* pid_buf = malloc(30);


	/* Envoi du nom de machine au lanceur */
	/* Envoi du pid au lanceur */
	sprintf(pid_buf, "%d\n", getpid());
	if( Sendline(fd, pid_buf, strlen(pid_buf)) < 0) { // Envoyer celle-ci au serveur
		puts("Send failed");
		return 1;
	}

	/* Create the listening socket */
	int sock_serv;
	struct sockaddr_in servaddr;

	if ( (sock_serv = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
		fprintf(stderr, "ECHOSERV: Error creating listening socket.\n");
		exit(EXIT_FAILURE);
	}

	/*Set all bytes in socket address structure to zero,
    and fill in the relevant data members */

	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(0);



	/* Bind our socket addresss to the listening socket,
     and call listen()*/
	int tr = 1;

	if (setsockopt(sock_serv,SOL_SOCKET,SO_REUSEADDR,&tr,sizeof(int)) == -1) {
		perror("setsockopt");
		exit(1);
	}
	if ( bind(sock_serv, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 ) {
		fprintf(stderr, "ECHOSERV: Error calling bind()\n");
		exit(EXIT_FAILURE);
	}

	if ( listen(sock_serv, LISTENQ) < 0 ) {
		fprintf(stderr, "ECHOSERV: Error calling listen()\n");
		exit(EXIT_FAILURE);
	}
	fprintf(stdout, "Attente de connexion\n");
	fflush(stdout);

	struct sockaddr_in serv_addr2;
	int addrlen = sizeof(serv_addr2);
	buffer[0] = '\0';
	getsockname(sock_serv, (struct sockaddr *) &serv_addr2, (socklen_t *) &addrlen);
	int new_port = (int) ntohs (serv_addr2.sin_port);
	char* new_ip =  inet_ntoa (serv_addr2.sin_addr);
	// GET HOST NAME
	char name[20];
	gethostname(name, sizeof(name));

	sprintf(buffer, "%s:%d\n",name, new_port);

	if( Sendline(fd, buffer, strlen(buffer)) < 0) { // Envoyer celle-ci au serveur
		puts("Send failed");
		return 1;
	}
	if( Readline(fd, buffer, MAXBUF-1) < 0) // Lire les informations des autres machines
	{
		puts("Read failed");
		return 1;
	}

	const char delimiters[] = ":";
	char *token1, *token2;

	token1 = strtok (buffer, delimiters);
	char *rang = malloc(strlen(token1));
	strcpy(rang, token1);
	token2 = strtok (NULL, delimiters);
	char *num_machines = malloc(strlen(token2));
	strcpy(num_machines, token2);
	int rangi = atoi(rang);
	int count = atoi(num_machines);
	char bufferx[MAXBUF];

	printf("rang:%d count:%d \n", atoi(rang), atoi(num_machines));
	fflush(stdout);


	if( Readline(fd, bufferx, MAXBUF-1) < 0)
	{
		puts("Read failed");
		return 1;
	}
	printf("bufferx: %s", bufferx);
	fflush(stdout);

	const char delimiters2[] = "-";

	char **token = malloc(count * sizeof(char*));

	token[0] = strtok (bufferx, delimiters2);

	for (j = 1; j < count; j++){
		token[j] = strtok (NULL, delimiters2);
	}

	int *fd_machine = malloc((count-rangi)*sizeof(int));




	// listen was here



	fd_set active_fd_set, tmpfds;

	/* FD_ZERO() clears out the different fdsets, so that
     it doesn't contain any file descriptors.*/

	FD_ZERO (&active_fd_set);
	FD_SET (sock_serv, &active_fd_set);


	for (j = rangi; j < count; j++){
		printf("connect to token[%d] %s\n",j , token[j]);
		fflush(stdout);
		create_socket_connect(token[j], &fd_machine[j-rangi]);
		FD_SET (fd_machine[j-rangi], &active_fd_set);
	}

	/*We initially have only one socket open, to receive new
    incoming connections. Initialise accordingly the tmpfds
    set with select MACRO*/

	int max = sock_serv;
	while (1) {
		tmpfds = active_fd_set;
		if (select(max+1, &tmpfds, NULL, NULL, NULL) < 0)
		{
			perror ("select");
			exit (EXIT_FAILURE);
		}

		/* calculate size of file descriptors table*/
		int i=0;
		int size = 0;
		int sockfd;

		/* The select() system call waits until any of the file descriptors
       specified in the read, sets given to it, is ready to give data */

		for (i = 3; i <= max; ++i) {
			if (FD_ISSET (i, &tmpfds)) {
				if (i == sock_serv) {
					/* Connection request on original socket. */
					size = sizeof (servaddr);
					sockfd = accept (sock_serv, (struct sockaddr *) &servaddr,
							(socklen_t *) &size);
					if (sockfd < 0)
					{
						perror ("accept");
						exit (EXIT_FAILURE);
					}
					fprintf (stderr,"Server: connect from host %s, port %d.\n",
							inet_ntoa(servaddr.sin_addr),
							(int) ntohs (servaddr.sin_port));
					FD_SET (sockfd, &active_fd_set);

					if(sockfd > max) max = sockfd;
				}

				/*Make the difference between a new client connection and data
      	  receveid from an already existing client*/
				else
				{

				}
			}
		}
	}



	/* Creation de la socket d'ecoute pour les */
	/* connexions avec les autres processus dsm */



	/* Envoi du numero de port au lanceur */
	/* pour qu'il le propage à tous les autres */
	/* processus dsm */

	/* on execute la bonne commande */
	return 0;
}
